home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / ISOLAN.ASM < prev    next >
Assembly Source File  |  1991-02-08  |  14KB  |  635 lines

  1. version    equ    1
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ; Packet driver for BICC Data Networks' ISOLAN 4110 ethernet
  6. ; controller, written by
  7. ;    Rainer Toebbicke
  8. ;    European Organisation of Nuclear Research (CERN)
  9. ;    Geneva, Switzerland
  10. ; based on the "generic" packet driver by Russell Nelson.
  11.  
  12.  
  13.  
  14. ; BICC ISOLAN card constants
  15.  
  16. IS_SAP    struc            ;Service Access Point channel
  17. IS_S_Data    db    ?    ;data semaphore
  18. IS_S_Taken    db    ?    ;taken semaphore
  19.         dw    ?
  20.  
  21. IS_S_Event    db    ?
  22.  
  23. IS_S_SrcEaddr    db    6 dup(?)    ;source Ethernet address
  24. IS_S_SrcLsap    db    ?
  25. IS_S_DstEaddr    db    6 dup(?)
  26. IS_S_DstLsap    db    ?
  27.         db    ?
  28. IS_S_Status    dw    ?
  29.         db    ?
  30. IS_S_SDUptr    dw    ?
  31. IS_SAP        ends
  32.  
  33. ; Bits defined in IS_S_Event
  34. IS_M_Init    equ    0ch
  35. IS_M_DataRq    equ    09h
  36. IS_M_DataInd    equ    0ah
  37. IS_Board_Init    equ    0dh
  38.  
  39.  
  40. IS        segment    at 0
  41.         org    8000h
  42. IS_Sign        db    ?        ;test for card presence
  43. IS_Reset    db    ?
  44. IS_Diagok    db    ?
  45. IS_Error    db    ?
  46. IS_ErrCode    db    ?
  47.         org    800eh
  48. IS_PgmStart    dw    ?
  49.  
  50. IS_IER        db    ?        ;interrupt enable register
  51. IS_I_Tx        equ    01h        ;transmit interrupt
  52. IS_I_Rx        equ    02h        ;receive interrupt
  53.  
  54. IS_ISR        db    ?        ;interrupt status reg
  55.         org    8014h
  56. IS_BlueBook    db    ?
  57. IS_LLC1        db    ?
  58. IS_Precv    db    ?        ;promiscuous receive flag
  59. IS_LanceRev    db    ?
  60. IS_MacReflSup    db    ?        ;MAC reflection suppression
  61.         org    8020h
  62. IS_Xmit        IS_SAP    <>        ;Transmit channel
  63.         org    8040h
  64. IS_Rcv        IS_SAP    <>        ;Receive channel
  65.         org    8060h
  66. IS_Eaddr    db    6 dup(?)    ;This card's Ethernet address
  67.  
  68. IS        ends
  69.  
  70.  
  71. IS_SDU        struc
  72. IS_SDU_DataOff    db    ?        ;offset to data
  73. IS_SDU_L    dw    ?        ;length of packet
  74. IS_SDU        ends
  75.  
  76.  
  77. ENET_HDR    equ    EADDR_LEN*2+2    ;length of ethernet header
  78.  
  79.  
  80.  
  81. code    segment    word public
  82.     assume    cs:code, ds:code
  83.  
  84.     public    int_no,    MemBase
  85. int_no    db    2,0,0,0            ;must be four bytes long for get_number.
  86. MemBase    dw    0b800h,0
  87.  
  88.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  89. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  90. driver_type    db    4+128        ;from the packet spec
  91. driver_name    db    'ISOLAN',0    ;name of the driver.
  92. driver_function    db    2
  93. parameter_list    label    byte
  94.     db    1    ;major rev of packet driver
  95.     db    9    ;minor rev of packet driver
  96.     db    14    ;length of parameter list
  97.     db    EADDR_LEN    ;length of MAC-layer address
  98.     dw    GIANT    ;MTU, including MAC headers
  99.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  100.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  101.     dw    0    ;(# of successive xmits) - 1
  102. int_num    dw    0    ;Interrupt # to hook for post-EOI
  103.             ;processing, 0 == none,
  104.  
  105.     public    rcv_modes
  106. rcv_modes    dw    4        ;number of receive modes in our table.
  107.         dw    0,0,0,rcv_mode_3
  108.  
  109.     include    movemem.asm
  110.  
  111.     public    as_send_pkt
  112. ; The Asynchronous Transmit Packet routine.
  113. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  114. ;   interrupts possibly enabled.
  115. ; Exit with nc if ok, or else cy if error, dh set to error number.
  116. ;   es:di and interrupt enable flag preserved on exit.
  117. as_send_pkt:
  118.     ret
  119.  
  120.     public    drop_pkt
  121. ; Drop a packet from the queue.
  122. ; Enter with es:di -> iocb.
  123. drop_pkt:
  124.     assume    ds:nothing
  125.     ret
  126.  
  127.     public    xmit
  128. ; Process a transmit interrupt with the least possible latency to achieve
  129. ;   back-to-back packet transmissions.
  130. ; May only use ax and dx.
  131. xmit:
  132.     assume    ds:nothing
  133.     ret
  134.  
  135.  
  136.     public    send_pkt
  137. send_pkt:
  138. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  139. ;  (only if the high-performance bit is set in driver_function)
  140. ;enter with ds:si -> packet, cx = packet length.
  141. ;exit with nc if ok, or else cy if error, dh set to error number.
  142.     assume    ds:nothing
  143.  
  144.     cld                ;moves go forward
  145.     mov    ax,MemBase
  146.     mov    es,ax            ;address the card
  147.     assume    es:IS
  148.     push    cx            ;save length
  149.  
  150. ; Wait for the transmit channel to become free
  151.     mov    cx,0ffffh        ;avoid infinite loop
  152. tx_wait:
  153.     test    IS_Xmit.IS_S_Data,0ffh
  154.     jnz    tx_idle
  155.     loop    tx_wait
  156.     pop    cx            ;remove from stack
  157.     mov    dh,CANT_SEND        ;transmit error
  158.     stc
  159.     ret
  160.  
  161. tx_idle:
  162.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  163.     mov    IS_Xmit.IS_S_Event,IS_M_DataRq    ;sending Data
  164.  
  165. ; copy destination ethernet addr
  166.     mov    cx,EADDR_LEN/2
  167.     lea    di,IS_Xmit.IS_S_DstEaddr
  168.     rep    movsw
  169.  
  170. ; copy source ethernet addr
  171.     mov    cx,EADDR_LEN/2
  172.     lea    di,IS_Xmit.IS_S_SrcEaddr
  173.     rep    movsw
  174.  
  175. ; copy type field
  176.     lodsw
  177.     xchg    ah,al                ;8086 order
  178.     mov    IS_Xmit.IS_S_Status,ax
  179.  
  180.     pop    cx                ;restore count
  181.     sub    cx,ENET_HDR            ;minus header
  182.  
  183.     mov    di,IS_Xmit.IS_S_SDUptr        ;point to SDU
  184.     mov    es:IS_SDU_L[di],cx        ;set count
  185.     xor    ah,ah
  186.     mov    al,es:IS_SDU_DataOff[di]
  187.     add    di,ax                ;point to data
  188.  
  189.     call    movemem                ; now copy the buffer
  190.  
  191.     mov    IS_Xmit.IS_S_Taken,1        ;release channel
  192.     clc                    ;no error occurred
  193.     ret
  194.     assume    es:nothing
  195.  
  196.  
  197.     public    get_address
  198. get_address:
  199. ;get the address of the interface.
  200. ;enter with es:di -> place to get the address, cx = size of address buffer.
  201. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  202.     assume    ds:code
  203.     cmp    cx,EADDR_LEN
  204.     jnb    get_addr_ok        ;buffer ok
  205.     stc
  206.     ret
  207.  
  208. get_addr_ok:
  209.     push    ds
  210.     push    si
  211.     mov    ax,MemBase        ;point to interface
  212.     mov    ds,ax
  213.     assume    ds:IS
  214.  
  215.     mov    si,offset IS_Eaddr    ;point to our E-net addr
  216.     mov    cx,EADDR_LEN/2
  217.     rep    movsw
  218.     pop    si
  219.     pop    ds
  220.     mov    cl,EADDR_LEN
  221.     clc
  222.     ret
  223.  
  224.  
  225.  
  226.     public    set_address
  227. set_address:
  228. ;enter with ds:si -> Ethernet address, CX = length of address.
  229. ;exit with nc if okay, or cy, dh=error if any errors.
  230.     assume    ds:nothing
  231.     cmp    cx,EADDR_LEN
  232.     jnb    set_addr_ok        ;buffer ok
  233.     mov    dh,BAD_ADDRESS
  234.     stc
  235.     ret
  236.  
  237. set_addr_ok:
  238.     push    es
  239.     push    di
  240.     mov    ax,MemBase        ;point to interface
  241.     mov    es,ax
  242.     assume    es:IS
  243.  
  244.     mov    di,offset IS_Eaddr    ;point to our E-net addr
  245.     mov    cx,EADDR_LEN/2
  246.     rep    movsw
  247.  
  248. ; reset the board's software, don't really know if this is needed
  249.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  250.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  251.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  252.  
  253. ; wait for request to complete
  254.     mov    cx,0ffffh        ;avoid infinite loop
  255. set_wait_2:
  256.     test    IS_Xmit.IS_S_Data,0ffh
  257.     jnz    set_done
  258.     loop    set_wait_2
  259.  
  260. set_done:
  261.     mov    cx,EADDR_LEN        ;return their address length.
  262.     pop    di
  263.     pop    es
  264.     assume    es:nothing
  265.     clc
  266.     ret
  267.  
  268.  
  269.  
  270. rcv_mode_3:
  271. ;receive mode 3 is the only one we support, so we don't have to do anything.
  272.     ret
  273.  
  274.  
  275.     public    set_multicast_list
  276. set_multicast_list:
  277. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  278. ;return nc if we set all of them, or cy,dh=error if we didn't.
  279.     mov    dh,NO_MULTICAST
  280.     stc
  281.     ret
  282.  
  283.  
  284.     public    terminate
  285. terminate:
  286.     ret
  287.  
  288.     public    reset_interface
  289. reset_interface:
  290. ;reset the interface.
  291.     assume    ds:code
  292.     push    ds
  293.     mov    ax,MemBase
  294.     mov    ds,ax
  295.     assume    ds:IS
  296.     mov    IS_IER,0
  297.     pop    ds
  298.     ret
  299.  
  300.  
  301. ;called when we want to determine what to do with a received packet.
  302. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  303.     extrn    recv_find: near
  304.  
  305. ;called after we have copied the packet into the buffer.
  306. ;enter with ds:si ->the packet, cx = length of the packet.
  307.     extrn    recv_copy: near
  308.  
  309.     extrn    count_in_err: near
  310.     extrn    count_out_err: near
  311.  
  312.     public    recv
  313. recv:
  314. ;called from the recv isr.  All registers have been saved, and ds=cs.
  315. ;Upon exit, the interrupt will be acknowledged.
  316.     assume    ds:code
  317.     mov    ax,MemBase
  318.     mov    ds,ax
  319.     assume    ds:IS
  320.  
  321.     mov    al,IS_ISR        ;get interrupt status
  322.     test    al,IS_I_RX        ;receive interrupt?
  323.     jnz    rcv_test_errors        ;yes...
  324.     jmp    rcv_done
  325.  
  326. rcv_test_errors:
  327.  
  328. ; some thorough testing missing here
  329. ; anyway, don't know what to test
  330.  
  331.  
  332. rcv_no_errors:
  333.     mov    IS_Rcv.IS_S_Data,0    ;block channel
  334.     mov    di,IS_Rcv.IS_S_SDUptr    ;point to SDU
  335.     mov    cx,IS_SDU_L[di]        ;get length
  336.     add    cx,ENET_HDR        ;plus ethernet header
  337.  
  338.  
  339. ; These following lines correctly point to the type field.
  340. ; However, addressability to the whole buffer on the 'receiver' call
  341. ; would be lost, a feature useful to some applications
  342.  
  343. ;    mov     ax,IS_Rcv.IS_S_Status ;get type field
  344. ;    xchg    ah,al         ;in network byte order
  345. ;    push    ax         ;have to place it somewhere
  346. ;    mov    di,sp
  347. ;    push    ss
  348. ;    pop    es            ;es:di at type field
  349.  
  350. ; The following 'hack' keeps addressability to the packet
  351. ; on the 'receiver' call but stays compatible with the
  352. ; packet driver skeleton.
  353. ; This feature is indicated by a bit in the type number (ugly)
  354. ; which the application can examine
  355.  
  356.     mov    al,IS_SDU_DataOff[di]    ;offset to to data
  357.     sub    al,2            ;offset to type field
  358.     cbw
  359.     add    di,ax            ;point to type field
  360.     push    ds
  361.     pop    es            ;es:di->type field
  362.  
  363.     push    cs
  364.     pop    ds            ;don't confuse recv_find
  365.     assume    ds:code
  366.  
  367.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  368.     mov    ax, es:[di]
  369.     xchg    ah, al
  370.     cmp     ax, 1500
  371.     ja    BlueBookPacket
  372.     inc    di            ;set di to 802.2 header
  373.     inc    di
  374.     mov    dl, IEEE8023
  375. BlueBookPacket:
  376.     call    recv_find        ;do we want this packet?
  377. ;    add    sp,2               ;remove type field
  378.  
  379.     mov    ax,es
  380.     or    ax,di
  381.     jz    rcv_done_0        ;pointer zero, give up
  382.  
  383.     push    es
  384.     push    di            ;save pointer
  385.  
  386.     mov    ax,MemBase
  387.     mov    ds,ax
  388.     assume    ds:IS
  389.  
  390. ; set up ethernet header
  391.     mov    cx,EADDR_LEN/2
  392.     mov    si,offset IS_Rcv.IS_S_DstEaddr
  393.     rep    movsw
  394.     mov    cx,EADDR_LEN/2
  395.     mov    si,offset IS_Rcv.IS_S_SrcEaddr
  396.     rep    movsw
  397.     mov    ax,IS_Rcv.IS_S_Status        ;type field
  398.     xchg    ah,al                ;in network byte order
  399.     stosw
  400.  
  401.     mov    si,IS_Rcv.IS_S_SDUptr        ;point to SDU
  402.     mov    cx,IS_SDU_L[si]            ;get length
  403.     push    cx                ;save for later
  404.     mov    al,IS_SDU_DataOff[si]
  405.     xor    ah,ah
  406.     add    si,ax                ;point to data
  407.  
  408.     call    movemem
  409.  
  410.     pop    cx            ;restore count
  411.     pop    si            ;restore pointer
  412.     pop    ds            ;restore pointer
  413.     assume    ds:nothing
  414.  
  415.     add    cx,ENET_HDR        ;adjust length
  416.     call    recv_copy        ;wake up client
  417.  
  418. rcv_done_0:
  419.     mov    ax,MemBase        ;point to interface
  420.     mov    ds,ax
  421.     assume    ds:IS
  422.  
  423. rcv_done:
  424.     mov    IS_Rcv.IS_S_Taken,1    ;release channel
  425.     mov    IS_ISR,0        ;clear interrupt
  426.     push    cs
  427.     pop    ds
  428.     assume    ds:code
  429.     ret
  430.  
  431.  
  432.     public    recv_exiting
  433. recv_exiting:
  434. ;called from the recv isr after interrupts have been acknowledged.
  435. ;Only ds and ax have been saved.
  436.     assume    ds:nothing
  437.     ret
  438.  
  439.  
  440. ;any code after this will not be kept after initialization.
  441. end_resident    label    byte
  442.  
  443.  
  444.     public    usage_msg
  445. usage_msg db "usage: ISOLAN [-n] [-d] [-w] <packet_int_no> <int_level>    <mem_addr>",CR,LF,'$'
  446.  
  447.     public    copyright_msg
  448. copyright_msg    db    "Packet    driver for BICC    ISOLAN device, version ",'0'+majver,".",'0'+version,CR,LF
  449.         db    "Portions Copyright 1989, R.Toebbicke, CERN, Switzerland",CR,LF
  450.         db    '$'
  451.  
  452. errmsg1    db    "No BICC Isolan    board found at this address.",CR,LF,'$'
  453. diag_errmsg    db    "Error - ISOLAN    Diagnostics failed.$"
  454.  
  455. diag_start_msg    db    "ISOLAN    Diagnostics running... $"
  456. diag_end_msg    db    " done.$"
  457.  
  458. int_no_name    db    "Interrupt number $"
  459. MemBaseName    db    "Shared    Memory address $"
  460. MemPrt    dw    0c000h,0
  461.  
  462.  
  463.  
  464.     extrn    set_recv_isr: near
  465.  
  466. ;enter with si -> argument string, di -> word to store.
  467. ;if there is no number, don't change the number.
  468.     extrn    get_number: near
  469.  
  470. ;enter with dx -> name of word, di -> dword to print.
  471.     extrn    print_number: near
  472.  
  473.     public    parse_args
  474. parse_args:
  475. ;exit with nc if all went well, cy otherwise.
  476.     mov    di,offset int_no
  477.     call    get_number
  478.     mov    di,offset MemPrt
  479.     call    get_number
  480.     mov    di,MemPrt
  481.     sub    di,800h            ;BICC standard notation
  482.     mov    MemBase,di
  483.     clc
  484.     ret
  485.  
  486.  
  487. bad_board:
  488.     mov    dx,offset errmsg1
  489. err_msg:
  490.     assume    ds:nothing
  491.     push    cs
  492.     pop    ds
  493.     mov    ah,9
  494.     int    21h
  495.     stc
  496.     ret
  497.  
  498.  
  499.     public    etopen
  500. etopen:
  501.     mov    ax,MemBase
  502.     mov    ds,ax
  503.     assume    ds:IS
  504.  
  505. ; test if board exists
  506.     mov    IS_Sign,42
  507.     cmp    IS_Sign,42
  508.     jne    bad_board
  509.  
  510.     mov    IS_Sign,0ffh-42
  511.     cmp    IS_Sign,0ffh-42
  512.     jne    bad_board
  513.  
  514.     cmp    IS_Reset,01h        ;already running?
  515.     je    diag_ok            ;yes, let it run
  516.  
  517.     mov    IS_Reset,0
  518.     mov    cx,0ffffh        ;avoid infinite loop
  519. diag_w_0:
  520.     cmp    IS_Reset,0fah
  521.     je    diag_1
  522.     loop    diag_w_0
  523.  
  524. diag_1:
  525.     mov    IS_Reset,0ffh
  526.     mov    cx,0ffffh        ;avoid infinite loop
  527. diag_w_1:
  528.     cmp    IS_Reset,0fah
  529.     je    diag_2
  530.     loop    diag_w_1
  531.  
  532. diag_2:
  533.     mov    IS_Reset,0e5h
  534.     mov    cx,0ffffh        ;avoid infinite loop
  535. diag_w_2:
  536.     cmp    IS_Reset,0fah
  537.     je    diag_3
  538.     loop    diag_w_2
  539.  
  540. diag_3:
  541.     mov    IS_Reset,09dh        ;start diagnostics
  542.  
  543.     push    ds
  544.     push    cs
  545.     pop    ds
  546.     mov    dx,offset diag_start_msg
  547.     mov    ah,9
  548.     int    21h
  549.     pop    ds
  550.  
  551.     mov    bx,050h            ;double loop, takes some time
  552. diag_w_3_0:
  553.     mov    cx,0ffffh        ;avoid infinite loop
  554. diag_w_3:
  555.     cmp    IS_Diagok,01h
  556.     je    diag_4
  557.     loop    diag_w_3
  558.     dec    bx
  559.     jnz    diag_w_3_0
  560.     mov    dx,offset diag_errmsg
  561.  
  562. diag_4:
  563.     push    ds
  564.     push    cs
  565.     pop    ds
  566.     mov    dx,offset diag_end_msg
  567.     mov    ah,9
  568.     int    21h
  569.     pop    ds
  570.  
  571.     mov    ax,0800h
  572.     mov    IS_PgmStart,ax
  573.     mov    IS_Reset,01h        ;run the program
  574.  
  575.  
  576. ; enable the board's interrupts
  577. diag_ok:
  578.     push    ds
  579.     push    cs
  580.     pop    ds            ;set cs=ds
  581.     call    set_recv_isr
  582.     pop    ds
  583.  
  584.     mov    IS_BlueBook,1        ;enable Blue Book MAC
  585.     mov    IS_LLC1,1        ;disable LLC1 service
  586.     mov    IS_MacReflSup,1        ;suppress MAC reflection
  587.     mov    IS_IER,IS_I_RX        ;enable for receive
  588.     mov    IS_ISR,0        ;clear previous
  589.  
  590. ; reset the board's software, just in case...
  591.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  592.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  593.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  594.  
  595. ; again wait for request to complete
  596.     mov    cx,0ffffh        ;avoid infinite loop
  597. in_wait_2:
  598.     test    IS_Xmit.IS_S_Data,0ffh
  599.     jnz    in_done
  600.     loop    in_wait_2
  601.  
  602. in_done:
  603.  
  604.     mov    al, int_no        ; Get board's interrupt vector
  605.     add    al, 8
  606.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  607.     jb    set_int_num        ; No.
  608.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  609. set_int_num:
  610.     xor    ah, ah            ; Clear high byte
  611.     mov    int_num, ax        ; Set parameter_list int num.
  612.  
  613. ;if all is okay,
  614.     mov    dx,offset end_resident
  615.     push    cs
  616.     pop    ds
  617.     clc
  618.     ret
  619.  
  620.     public    print_parameters
  621. print_parameters:
  622. ;echo our command-line parameters
  623.     mov    di,offset int_no
  624.     mov    dx,offset int_no_name
  625.     call    print_number
  626.     mov    di,offset MemPrt
  627.     mov    dx,offset MemBaseName
  628.     call    print_number
  629.     ret
  630.  
  631.  
  632. code    ends
  633.  
  634.     end
  635.